﻿using Pipes.Json;
using Pipes.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;

namespace Pipes.UnitTest
{
    
    
    /// <summary>
    ///This is a test class for JsonTextWriterTest and is intended
    ///to contain all JsonTextWriterTest Unit Tests
    ///</summary>
  [TestClass()]
  public class JsonParseRenderTest
  {


    private TestContext testContextInstance;

    /// <summary>
    ///Gets or sets the test context which provides
    ///information about and functionality for the current test run.
    ///</summary>
    public TestContext TestContext
    {
      get
      {
        return testContextInstance;
      }
      set
      {
        testContextInstance = value;
      }
    }

    #region Additional test attributes
    // 
    //You can use the following additional attributes as you write your tests:
    //
    //Use ClassInitialize to run code before running the first test in the class
    //[ClassInitialize()]
    //public static void MyClassInitialize(TestContext testContext)
    //{
    //}
    //
    //Use ClassCleanup to run code after all tests in a class have run
    //[ClassCleanup()]
    //public static void MyClassCleanup()
    //{
    //}
    //
    //Use TestInitialize to run code before running each test
    //[TestInitialize()]
    //public void MyTestInitialize()
    //{
    //}
    //
    //Use TestCleanup to run code after each test has run
    //[TestCleanup()]
    //public void MyTestCleanup()
    //{
    //}
    //
    #endregion

    private void ParseRenderTest(string expected)
    {
      ParseRenderTest(expected, expected, true);
    }
    private void ParseRenderTest(string start, string expected, bool strict)
    {
      var reader = new IO.StringTextSource(start).Pipe(new Json.JsonTextReader());
      reader.StrictConformance = strict;
      var writer = new StringWriter();
      var json = new Json.JsonTextWriter(writer);
      json.UseEscapedUnicode = true;
      reader.WriteTo(json);
      json.Flush();
      string result = writer.ToString();
      Assert.AreEqual(expected, result);
    }
    private void ParseFailingValue(string start)
    {
      var exceptionRaised = false;
      try
      {
        var reader = new IO.StringTextSource(start).Pipe(new Json.JsonTextReader());
        foreach (var node in reader)
        {
          // Do nothing but read
        }
      }
      catch
      {
        exceptionRaised = true;
      }
      Assert.AreEqual(true, exceptionRaised);
    }

    [TestMethod()]
    public void JsonParse_Fail01()
    {
      ParseFailingValue(@"""A JSON payload should be an object or array, not a string.""");
    }

    [TestMethod()]
    public void JsonParse_Fail02()
    {
      ParseFailingValue(@"[""Unclosed array""");
    }

    [TestMethod()]
    public void JsonParse_Fail03()
    {
      ParseFailingValue(@"{unquoted_key: ""keys must be quoted""}");
    }

    [TestMethod()]
    public void JsonParse_Fail03_PassNonStrict()
    {
      ParseRenderTest(@"{unquoted_key: ""keys must be quoted""}", @"{""unquoted_key"":""keys must be quoted""}", false);
    }

    [TestMethod()]
    public void JsonParse_Fail04()
    {
      ParseFailingValue(@"[""extra comma"",]");
    }

    [TestMethod()]
    public void JsonParse_Fail05()
    {
      ParseFailingValue(@"[""double extra comma"",,]");
    }

    [TestMethod()]
    public void JsonParse_Fail06()
    {
      ParseFailingValue(@"[   , ""<-- missing value""]");
    }

    [TestMethod()]
    public void JsonParse_Fail07()
    {
      ParseFailingValue(@"[""Comma after the close""],");
    }

    [TestMethod()]
    public void JsonParse_Fail08()
    {
      ParseFailingValue(@"[""Extra close""]]");
    }

    [TestMethod()]
    public void JsonParse_Fail09()
    {
      ParseFailingValue(@"{""Extra comma"": true,}");
    }

    [TestMethod()]
    public void JsonParse_Fail10()
    {
      ParseFailingValue(@"{""Extra value after close"": true} ""misplaced quoted value""");
    }

    [TestMethod()]
    public void JsonParse_Fail11()
    {
      ParseFailingValue(@"{""Illegal expression"": 1 + 2}");
    }

    [TestMethod()]
    public void JsonParse_Fail12()
    {
      ParseFailingValue(@"{""Illegal invocation"": alert()}");
    }

    [TestMethod()]
    public void JsonParse_Fail13()
    {
      ParseFailingValue(@"{""Numbers cannot have leading zeroes"": 013}");
    }

    [TestMethod()]
    public void JsonParse_Fail14()
    {
      ParseFailingValue(@"{""Numbers cannot be hex"": 0x14}");
    }

    [TestMethod()]
    public void JsonParse_Fail15()
    {
      ParseFailingValue(@"[""Illegal backslash escape: \x15""]");
    }

    [TestMethod()]
    public void JsonParse_Fail16()
    {
      ParseFailingValue(@"[\naked]");
    }

    [TestMethod()]
    public void JsonParse_Fail17()
    {
      ParseFailingValue(@"[""Illegal backslash escape: \017""]");
    }

    [TestMethod()]
    public void JsonParse_Fail18()
    {
      ParseFailingValue(@"[[[[[[[[[[[[[[[[[[[[""Too deep""]]]]]]]]]]]]]]]]]]]]");
    }

    [TestMethod()]
    public void JsonParse_Fail19()
    {
      ParseFailingValue(@"{""Missing colon"" null}");
    }

    [TestMethod()]
    public void JsonParse_Fail20()
    {
      ParseFailingValue(@"{""Double colon"":: null}");
    }

    [TestMethod()]
    public void JsonParse_Fail21()
    {
      ParseFailingValue(@"{""Comma instead of colon"", null}");
    }

    [TestMethod()]
    public void JsonParse_Fail22()
    {
      ParseFailingValue(@"[""Colon instead of comma"": false]");
    }

    [TestMethod()]
    public void JsonParse_Fail23()
    {
      ParseFailingValue(@"[""Bad value"", truth]");
    }

    [TestMethod()]
    public void JsonParse_Fail24()
    {
      ParseFailingValue(@"['single quote']");
    }

    [TestMethod()]
    public void JsonParse_Fail25()
    {
      ParseFailingValue(@"[""	tab	character	in	string	""]");
    }

    [TestMethod()]
    public void JsonParse_Fail26()
    {
      ParseFailingValue(@"[""tab\   character\   in\  string\  ""]");
    }

    [TestMethod()]
    public void JsonParse_Fail27()
    {
      ParseFailingValue("[\"line\r\nbreak\"]");
    }

    [TestMethod()]
    public void JsonParse_Fail28()
    {
      ParseFailingValue("[\"line\\\r\nbreak\"]");
    }

    [TestMethod()]
    public void JsonParse_Fail29()
    {
      ParseFailingValue(@"[0e]");
    }

    [TestMethod()]
    public void JsonParse_Fail30()
    {
      ParseFailingValue(@"[0e+]");
    }

    [TestMethod()]
    public void JsonParse_Fail31()
    {
      ParseFailingValue(@"[0e+-1]");
    }

    [TestMethod()]
    public void JsonParse_Fail32()
    {
      ParseFailingValue(@"{""Comma instead if closing brace"": true,");
    }

    [TestMethod()]
    public void JsonParse_Fail33()
    {
      ParseFailingValue(@"[""mismatch""}");
    }

    [TestMethod()]
    public void JsonParseRender_ValueFormatting()
    {
      ParseRenderTest(@"[""@"",""\r\n\t\f\b?{\\r\\n\""'"",true,10,10.99,0.99,1E-18,null,null,3,""This is a string.""]");
    }

    [TestMethod()]
    public void JsonParseRender_StringEscaping()
    {
      ParseRenderTest(@"[""\""These pretzels are making me thirsty!\"""",""Jeff's house was burninated."",""1. You don't talk about fight club.\r\n2. You don't talk about fight club."",""35% of\t statistics\n are made\r up.""]");
    }

    [TestMethod()]
    public void JsonParseRender_ValidPattern1()
    {
      ParseRenderTest(@"[     ""JSON Test Pattern pass1"",     {""object with 1 member"":[""array with 1 element""]},     {},     [],     -42,     true,     false,     null,     {         ""integer"": 1234567890,         ""real"": -9876.543210,         ""e"": 0.123456789e-12,         ""E"": 1.234567890E+34,         """":  23456789012E66,         ""zero"": 0,         ""one"": 1,         ""space"": "" "",         ""quote"": ""\"""",         ""backslash"": ""\\"",         ""controls"": ""\b\f\n\r\t"",         ""slash"": ""/ & \/"",         ""alpha"": ""abcdefghijklmnopqrstuvwyz"",         ""ALPHA"": ""ABCDEFGHIJKLMNOPQRSTUVWYZ"",         ""digit"": ""0123456789"",         ""0123456789"": ""digit"",         ""special"": ""`1~!@#$%^&*()_+-={':[,]}|;.</>?"",         ""hex"": ""\u0123\u4567\u89AB\uCDEF\uabcd\uef4A"",         ""true"": true,         ""false"": false,         ""null"": null,         ""array"":[  ],         ""object"":{  },         ""address"": ""50 St. James Street"",         ""url"": ""http://www.JSON.org/"",         ""comment"": ""// /* <!-- --"",         ""# -- --> */"": "" "",         "" s p a c e d "" :[1,2 , 3  ,  4 , 5        ,          6           ,7        ],""compact"":[1,2,3,4,5,6,7],         ""jsontext"": ""{\""object with 1 member\"":[\""array with 1 element\""]}"",         ""quotes"": ""&#34; \u0022 %22 0x22 034 &#x22;"",         ""\/\\\""\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"" : ""A key can be any string""     },     0.5 ,98.6 , 99.44 ,  1066, 1e1, 0.1e1, 1e-1, 1e00,2e+00,2e-00 ,""rosebud""]",
        @"[""JSON Test Pattern pass1"",{""object with 1 member"":[""array with 1 element""]},{},[],-42,true,false,null,{""integer"":1234567890,""real"":-9876.54321,""e"":1.23456789E-13,""E"":1.23456789E+34,"""":2.3456789012E+76,""zero"":0,""one"":1,""space"":"" "",""quote"":""\"""",""backslash"":""\\"",""controls"":""\b\f\n\r\t"",""slash"":""/ & /"",""alpha"":""abcdefghijklmnopqrstuvwyz"",""ALPHA"":""ABCDEFGHIJKLMNOPQRSTUVWYZ"",""digit"":""0123456789"",""0123456789"":""digit"",""special"":""`1~!@#$%^&*()_+-={':[,]}|;.</>?"",""hex"":""\u0123\u4567\u89AB\uCDEF\uABCD\uEF4A"",""true"":true,""false"":false,""null"":null,""array"":[],""object"":{},""address"":""50 St. James Street"",""url"":""http://www.JSON.org/"",""comment"":""// /* <!-- --"",""# -- --> */"":"" "","" s p a c e d "":[1,2,3,4,5,6,7],""compact"":[1,2,3,4,5,6,7],""jsontext"":""{\""object with 1 member\"":[\""array with 1 element\""]}"",""quotes"":""&#34; \"" %22 0x22 034 &#x22;"",""/\\\""\uCAFE\uBABE\uAB98\uFCDE\uBCDA\uEF4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"":""A key can be any string""},0.5,98.6,99.44,1066,10,1,0.1,1,2,2,""rosebud""]", true);
    }

    [TestMethod()]
    public void JsonParseRender_ValidPattern2()
    {
      ParseRenderTest(@"{""JSON Test Pattern pass3"":{""The outermost value"":""must be an object or array."",""In this test"":""It is an object.""}}");
    }

    [TestMethod()]
    public void JsonParseRender_ArrayDepth()
    {
      ParseRenderTest(@"[[[[[[[[[[[[[[[[[[[""Not too deep""]]]]]]]]]]]]]]]]]]]");
    }

    /// <summary>
    ///A test for Array
    ///</summary>
    [TestMethod()]
    public void JsonTextWriter_ValueFormatting()
    {
      var writer = new StringWriter();
      var json = new JsonTextWriter(writer);

      json.Array();
      json.Value('@');
      json.Value("\r\n\t\f\b?{\\r\\n\"\'");
      json.Value(true);
      json.Value(10);
      json.Value(10.99);
      json.Value(0.99);
      json.Value(0.000000000000000001d);
      json.Value(0.000000000000000001m);
      json.Value((string)null);
      json.Value((object)null);
      json.Value(System.IO.FileAccess.ReadWrite);
      json.Value("This is a string.");
      json.ArrayEnd();
      json.Flush();
      
      string expected = @"[""@"",""\r\n\t\f\b?{\\r\\n\""'"",true,10,10.99,0.99,1E-18,0.000000000000000001,null,null,3,""This is a string.""]";
      string result = writer.ToString();
      Assert.AreEqual(expected, result);
    }

    [TestMethod()]
    public void JsonToXml_SimpleTest()
    {
      TestXmlConversion(@"{""a"":{""b"":[{""@v"":""thing"",""#text"":""value""},""two""],""e"":""2"",""d"":{""e"":""1"",""g"":""3""},""f"":{""@v"":""thing"",""@x"":""another"",""#text"":""val""}}}",
        @"<a><b v=""thing"">value</b><b>two</b><e>2</e><d><e>1</e><g>3</g></d><f v=""thing"" x=""another"">val</f></a>");
    }

    [TestMethod()]
    public void JsonToXml_AmlTest()
    {
      TestXmlConversion(@"{""SOAP-ENV:Envelope"":{""@xmlns:SOAP-ENV"":""http://schemas.xmlsoap.org/soap/envelope/"",""SOAP-ENV:Body"":{""Result"":{""Item"":[{""@type"":""Person"",""@typeId"":""A4AFA282D2F949C8B3B400CB313A634A"",""@id"":""3F728327F68A4F439C36FBB93704E202"",""email"":""eric.walstra@gentex.com"",""id"":{""@keyed_name"":""Eric Walstra"",""@type"":""Person"",""#text"":""3F728327F68A4F439C36FBB93704E202""},""location"":{""@keyed_name"":""Gentex: Centennial"",""@type"":""Site"",""Item"":{""@type"":""Site"",""@typeId"":""52EC3DA140EB49F9A12AE3B344581FA6"",""@id"":""25B7A4B0F9ED4EC593729EDDBEA52D3B"",""id"":{""@keyed_name"":""Gentex: Centennial"",""@type"":""Site"",""#text"":""25B7A4B0F9ED4EC593729EDDBEA52D3B""}}},""manager"":{""@keyed_name"":""Kenneth Horner"",""@type"":""Person"",""#text"":""A628DE16A60248B1939C162022558D66""}},{""@type"":""Person"",""@typeId"":""A4AFA282D2F949C8B3B400CB313A634A"",""@id"":""13E517A572A54A45B4187657346438C5"",""email"":{""@is_null"":""1""},""id"":{""@keyed_name"":""Eric Watson"",""@type"":""Person"",""#text"":""13E517A572A54A45B4187657346438C5""},""location"":{""@keyed_name"":""Gentex: State"",""@type"":""Site"",""Item"":{""@type"":""Site"",""@typeId"":""52EC3DA140EB49F9A12AE3B344581FA6"",""@id"":""C86DCDBCD44448619DF85061A0A2F762"",""id"":{""@keyed_name"":""Gentex: State"",""@type"":""Site"",""#text"":""C86DCDBCD44448619DF85061A0A2F762""}}},""manager"":{""@keyed_name"":""Robert Vandervennen"",""@type"":""Person"",""#text"":""92A54C30E1994A8DBDFB9654D133CCF3""}},{""@type"":""Person"",""@typeId"":""A4AFA282D2F949C8B3B400CB313A634A"",""@id"":""C1210AFB342A4B509B4F6B6B6538BCB7"",""email"":""eric.woodward@gentex.com"",""id"":{""@keyed_name"":""Eric Woodward"",""@type"":""Person"",""#text"":""C1210AFB342A4B509B4F6B6B6538BCB7""},""location"":{""@keyed_name"":""Gentex: Centennial"",""@type"":""Site"",""Item"":{""@type"":""Site"",""@typeId"":""52EC3DA140EB49F9A12AE3B344581FA6"",""@id"":""25B7A4B0F9ED4EC593729EDDBEA52D3B"",""id"":{""@keyed_name"":""Gentex: Centennial"",""@type"":""Site"",""#text"":""25B7A4B0F9ED4EC593729EDDBEA52D3B""}}},""manager"":{""@keyed_name"":""Paul Flynn"",""@type"":""Person"",""#text"":""E6B5BE1247894283877EC3D02CA77FDB""}},{""@type"":""Person"",""@typeId"":""A4AFA282D2F949C8B3B400CB313A634A"",""@id"":""A3F18443E8EF49CCA74DB54410E0F0E0"",""email"":""eric.woodwyk@gentex.com"",""id"":{""@keyed_name"":""Eric Woodwyk"",""@type"":""Person"",""#text"":""A3F18443E8EF49CCA74DB54410E0F0E0""},""location"":{""@keyed_name"":""Gentex: Centennial"",""@type"":""Site"",""Item"":{""@type"":""Site"",""@typeId"":""52EC3DA140EB49F9A12AE3B344581FA6"",""@id"":""25B7A4B0F9ED4EC593729EDDBEA52D3B"",""id"":{""@keyed_name"":""Gentex: Centennial"",""@type"":""Site"",""#text"":""25B7A4B0F9ED4EC593729EDDBEA52D3B""}}},""manager"":{""@keyed_name"":""Sherwood Brown"",""@type"":""Person"",""#text"":""EFF308B60729446CBA0E2EBFCF2957ED""}},{""@type"":""Person"",""@typeId"":""A4AFA282D2F949C8B3B400CB313A634A"",""@id"":""40A4E99E9B534214B872A6BD448C72B5"",""email"":{""@is_null"":""1""},""id"":{""@keyed_name"":""Eric Woolpert"",""@type"":""Person"",""#text"":""40A4E99E9B534214B872A6BD448C72B5""},""location"":{""@keyed_name"":""Gentex: State"",""@type"":""Site"",""Item"":{""@type"":""Site"",""@typeId"":""52EC3DA140EB49F9A12AE3B344581FA6"",""@id"":""C86DCDBCD44448619DF85061A0A2F762"",""id"":{""@keyed_name"":""Gentex: State"",""@type"":""Site"",""#text"":""C86DCDBCD44448619DF85061A0A2F762""}}},""manager"":{""@keyed_name"":""Scott Kazmer"",""@type"":""Person"",""#text"":""297FA42D2AD14B7A99998CCB1C38A263""}},null]}}}}",
        @"<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/""><SOAP-ENV:Body><Result><Item type=""Person"" typeId=""A4AFA282D2F949C8B3B400CB313A634A"" id=""3F728327F68A4F439C36FBB93704E202""><email>eric.walstra@gentex.com</email><id keyed_name=""Eric Walstra"" type=""Person"">3F728327F68A4F439C36FBB93704E202</id><location keyed_name=""Gentex: Centennial"" type=""Site""><Item type=""Site"" typeId=""52EC3DA140EB49F9A12AE3B344581FA6"" id=""25B7A4B0F9ED4EC593729EDDBEA52D3B""><id keyed_name=""Gentex: Centennial"" type=""Site"">25B7A4B0F9ED4EC593729EDDBEA52D3B</id></Item></location><manager keyed_name=""Kenneth Horner"" type=""Person"">A628DE16A60248B1939C162022558D66</manager></Item><Item type=""Person"" typeId=""A4AFA282D2F949C8B3B400CB313A634A"" id=""13E517A572A54A45B4187657346438C5""><email is_null=""1"" /><id keyed_name=""Eric Watson"" type=""Person"">13E517A572A54A45B4187657346438C5</id><location keyed_name=""Gentex: State"" type=""Site""><Item type=""Site"" typeId=""52EC3DA140EB49F9A12AE3B344581FA6"" id=""C86DCDBCD44448619DF85061A0A2F762""><id keyed_name=""Gentex: State"" type=""Site"">C86DCDBCD44448619DF85061A0A2F762</id></Item></location><manager keyed_name=""Robert Vandervennen"" type=""Person"">92A54C30E1994A8DBDFB9654D133CCF3</manager></Item><Item type=""Person"" typeId=""A4AFA282D2F949C8B3B400CB313A634A"" id=""C1210AFB342A4B509B4F6B6B6538BCB7""><email>eric.woodward@gentex.com</email><id keyed_name=""Eric Woodward"" type=""Person"">C1210AFB342A4B509B4F6B6B6538BCB7</id><location keyed_name=""Gentex: Centennial"" type=""Site""><Item type=""Site"" typeId=""52EC3DA140EB49F9A12AE3B344581FA6"" id=""25B7A4B0F9ED4EC593729EDDBEA52D3B""><id keyed_name=""Gentex: Centennial"" type=""Site"">25B7A4B0F9ED4EC593729EDDBEA52D3B</id></Item></location><manager keyed_name=""Paul Flynn"" type=""Person"">E6B5BE1247894283877EC3D02CA77FDB</manager></Item><Item type=""Person"" typeId=""A4AFA282D2F949C8B3B400CB313A634A"" id=""A3F18443E8EF49CCA74DB54410E0F0E0""><email>eric.woodwyk@gentex.com</email><id keyed_name=""Eric Woodwyk"" type=""Person"">A3F18443E8EF49CCA74DB54410E0F0E0</id><location keyed_name=""Gentex: Centennial"" type=""Site""><Item type=""Site"" typeId=""52EC3DA140EB49F9A12AE3B344581FA6"" id=""25B7A4B0F9ED4EC593729EDDBEA52D3B""><id keyed_name=""Gentex: Centennial"" type=""Site"">25B7A4B0F9ED4EC593729EDDBEA52D3B</id></Item></location><manager keyed_name=""Sherwood Brown"" type=""Person"">EFF308B60729446CBA0E2EBFCF2957ED</manager></Item><Item type=""Person"" typeId=""A4AFA282D2F949C8B3B400CB313A634A"" id=""40A4E99E9B534214B872A6BD448C72B5""><email is_null=""1"" /><id keyed_name=""Eric Woolpert"" type=""Person"">40A4E99E9B534214B872A6BD448C72B5</id><location keyed_name=""Gentex: State"" type=""Site""><Item type=""Site"" typeId=""52EC3DA140EB49F9A12AE3B344581FA6"" id=""C86DCDBCD44448619DF85061A0A2F762""><id keyed_name=""Gentex: State"" type=""Site"">C86DCDBCD44448619DF85061A0A2F762</id></Item></location><manager keyed_name=""Scott Kazmer"" type=""Person"">297FA42D2AD14B7A99998CCB1C38A263</manager></Item><Item /></Result></SOAP-ENV:Body></SOAP-ENV:Envelope>");
    }

    public void JsonToXml_AmlTest2()
    {
      TestXmlConversion(@"{""Item"":{""@isNew"":""1"",""@type"":""Post Reply"",""@action"":""add"",""source_id"":""F6C6547B847B489285F512BE49C78F3E"",""comments"":""Makes sense to me.""}}",
        @"<Item isNew=""1"" type=""Post Reply"" action=""add""><source_id>F6C6547B847B489285F512BE49C78F3E</source_id><comments>Makes sense to me.</comments></Item>");
    }

    [TestMethod()]
    public void JsonToXml_NullTextTest()
    {
      TestXmlConversion(@"{""Item"":{""@isNew"":""1"",""@type"":""Post"",""@action"":""add"",""description"":{""@is_null"":""1"",""#text"":null},""name"":{""@is_null"":""1"",""#text"":null},""item_config_id"":""730B9DFC04F6419482DB275967FB63DC"",""itemtype_id"":{""Item"":{""@isNew"":""1"",""@type"":""ItemType"",""@action"":""get"",""name"":""Express ECO""}}}}",
        @"<Item isNew=""1"" type=""Post"" action=""add""><description is_null=""1""></description><name is_null=""1""></name><item_config_id>730B9DFC04F6419482DB275967FB63DC</item_config_id><itemtype_id><Item isNew=""1"" type=""ItemType"" action=""get""><name>Express ECO</name></Item></itemtype_id></Item>");
    }

    void TestXmlConversion(string input, string expected)
    {
      var reader = new IO.StringTextSource(input).Pipe(new Json.JsonTextReader()).Pipe(new Xml.XmlJsonReader());
      using (var writer = new StringWriter())
      {
        var settings = new Xml.XmlWriterSettings();
        settings.OmitXmlDeclaration = true;
        using (var xml = Xml.XmlTextWriter.Create(writer, settings))
        {
          reader.WriteTo(xml);
        }
        Assert.AreEqual(expected, writer.ToString());
      }
    }

    [TestMethod()]
    public void JsonTextWriter_NullableValueFormatting()
    {
      var writer = new StringWriter();
      var json = new JsonTextWriter(writer);

      json.Array();
      json.Value((char?)null);
      json.Value((char?)'c');
      json.Value((bool?)null);
      json.Value((bool?)true);
      json.Value((byte?)null);
      json.Value((byte?)1);
      json.Value((sbyte?)null);
      json.Value((sbyte?)1);
      json.Value((short?)null);
      json.Value((short?)1);
      json.Value((ushort?)null);
      json.Value((ushort?)1);
      json.Value((int?)null);
      json.Value((int?)1);
      json.Value((uint?)null);
      json.Value((uint?)1);
      json.Value((long?)null);
      json.Value((long?)1);
      json.Value((ulong?)null);
      json.Value((ulong?)1);
      json.Value((double?)null);
      json.Value((double?)1.1);
      json.Value((float?)null);
      json.Value((float?)1.1);
      json.Value((decimal?)null);
      json.Value((decimal?)1.1m);
      json.Value((DateTime?)null);
      json.ArrayEnd();
      json.Flush();
      
      string expected = @"[null,""c"",null,true,null,1,null,1,null,1,null,1,null,1,null,1,null,1,null,1,null,1.1,null,1.1,null,1.1,null]";
      string result = writer.ToString();
      Assert.AreEqual(expected, result);
    }

    [TestMethod()]
    public void JsonTextWriter_StringEscaping()
    {
      var writer = new StringWriter();
      var json = new JsonTextWriter(writer);

      json.Array();
      json.Value(@"""These pretzels are making me thirsty!""");
      json.Value("Jeff's house was burninated.");
      json.Value(@"1. You don't talk about fight club.
2. You don't talk about fight club.");
      json.Value("35% of\t statistics\n are made\r up.");
      json.ArrayEnd();
      json.Flush();

      string expected = @"[""\""These pretzels are making me thirsty!\"""",""Jeff's house was burninated."",""1. You don't talk about fight club.\r\n2. You don't talk about fight club."",""35% of\t statistics\n are made\r up.""]";
      string result = writer.ToString();
      Assert.AreEqual(expected, result);
    }
  }
}
